/*
 * BaseSocket.cpp
 *
 *  Created on: 2012-12-14
 *      Author: yangentao@gmail.com
 */

#include "BaseSocket.h"
#include <assert.h>

namespace yet {

BaseSocket::BaseSocket() {
	sock = INVALID_SOCKET;
}
BaseSocket::BaseSocket(SOCKET s) {
	sock = s;
}

BaseSocket::~BaseSocket() {
}

BaseSocket::operator SOCKET(){
	return sock;
}

void BaseSocket::close() {
	if (isValidSocket()) {
		closesocket(sock);
		sock = INVALID_SOCKET;
	}
}
void BaseSocket::setInvalid(){
	sock = INVALID_SOCKET;
}
bool BaseSocket::getSockName(InetAddr* outAddr) {
	assert(outAddr);
	int len = 0;
	return 0 == getsockname(sock, outAddr->getAddr(), &len);
}

bool BaseSocket::getPeerName(InetAddr* outAddr) {
	assert(outAddr);
	int len = 0;
	return 0 == getpeername(sock, outAddr->getAddr(), &len);
}

bool BaseSocket::createTcpSocket() {
	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	return INVALID_SOCKET != sock;
}
bool BaseSocket::createUdpSocket() {
	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	return INVALID_SOCKET != sock;
}

bool BaseSocket::isValidSocket() {
	return INVALID_SOCKET != sock;
}

bool BaseSocket::listen() {
	return listen(SOMAXCONN);
}
bool BaseSocket::listen(int backlog) {
	return 0 == ::listen(sock, backlog);
}

bool BaseSocket::bind(InetAddr addr) {
	return 0 == ::bind(sock, addr.getAddr(), addr.getSize());
}
bool BaseSocket::bind() {
	InetAddr addr(0);
	return bind(addr);
}

bool BaseSocket::bind(short localPort) {
	InetAddr addr(localPort);
	return bind(addr);
}
bool BaseSocket::bind(string localIp, short localPort) {
	InetAddr addr(localIp, localPort);
	return bind(addr);
}

SOCKET BaseSocket::accept(InetAddr* outAddr) {
	int size = 0;
	return ::accept(sock, outAddr ? outAddr->getAddr() : 0, outAddr ? &size : 0);
}
int BaseSocket::connect(InetAddr peerAddr) {
	assert(isValidSocket());
	return ::connect(sock, peerAddr.getAddr(), peerAddr.getSize());
}
int BaseSocket::connect(string ip, short port) {
	assert(!ip.empty());
	assert(port > 0);
	return connect(InetAddr(ip, port));
}
int BaseSocket::send(const char* buffer, int size, int flag) {
	assert(isValidSocket());
	assert(size >= 0);
	return ::send(sock, buffer, size, flag);
}
int BaseSocket::send(const char* buffer, int size) {
	return send(buffer, size, 0);
}
int BaseSocket::sendOOB(const char* buffer, int size) {
	return send(buffer, size, MSG_OOB);
}

int BaseSocket::recv(char* buffer, int size, int flag) {
	return ::recv(sock, buffer, size, flag);
}
int BaseSocket::recv(char* buffer, int size) {
	return recv(buffer, size, 0);
}
int BaseSocket::recvOOB(char* buffer, int size) {
	return recv(buffer, size, MSG_OOB);
}
int BaseSocket::sendTo(InetAddr peerAddr, const char* buf, int len) {
	return ::sendto(sock, buf, len, 0, peerAddr.getAddr(), peerAddr.getSize());
}

int BaseSocket::recvFrom(InetAddr* outPeerAddr, char* buf, int len) {
	int size = 0;
	return recvfrom(sock, buf, len, 0, outPeerAddr ? outPeerAddr->getAddr() : 0, outPeerAddr ? &size : 0);
}

int BaseSocket::select(FdSet* rSet, FdSet* wSet, FdSet* eSet, int seconds, int usec) {
	struct timeval t;
	t.tv_sec = seconds;
	t.tv_usec = usec;
	return ::select(0, rSet ? &rSet->fdset : 0, wSet ? &wSet->fdset : 0, eSet ? &eSet->fdset : 0, &t);
}
int BaseSocket::ioctl(long cmd, u_long* arg) {
	return ioctlsocket(sock, cmd, arg);
}
int BaseSocket::ioctlNoBlock(u_long noblock) {
	return ioctl(FIONBIO, &noblock);
}
int BaseSocket::ioctlRead(u_long* n) {
	return ioctl(FIONREAD, n);
}

} /* namespace yet */
